EDA: Caracterización y distribución de los datos#
Líbrerias y modulos necesarios#
import json
import warnings
import pandas as pd
import plotly.express as px
warnings.filterwarnings('ignore')
import plotly.graph_objects as go
from urllib.request import urlopen
from funciones import *
Conjunto de datos#
url = r"https://github.com/sePerezAlbor/Data/blob/main/data_analisis.xlsx?raw=true"
data = pd.read_excel(url, na_values = [" "])
data.head()
| region | Nombre_Departamento | Nombre_Municipio | sitio_def | año_def | mes_def | sexo | estado_civil | grupo_edad | nivel_edu | seg_social | asistencia_med | causa_basica | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Orinoquía | META | VILLAVICENCIO | Casa | 1985 | Enero | Femenino | Casado | 45-49 años | No especificado | Otro | NO | Parte no especificada |
| 1 | Andina | BOYACÁ | VENTAQUEMADA | Casa | 1985 | Enero | Femenino | Soltero | 85+ años | No especificado | Otro | NO | Parte no especificada |
| 2 | Orinoquía | META | PUERTO LÓPEZ | Casa | 1985 | Enero | Femenino | Casado | 50-54 años | No especificado | Otro | NO | Parte no especificada |
| 3 | Andina | HUILA | NEIVA | Hospital o Clínica | 1985 | Enero | Femenino | Casado | 35-39 años | No especificado | Otro | NO | Parte no especificada |
| 4 | Andina | HUILA | NEIVA | Casa | 1985 | Enero | Femenino | Casado | 75-79 años | No especificado | Otro | NO | Parte no especificada |
data.shape
(78479, 13)
Análisis general del conjunto de datos#
# Dividir en dos grupos (ajusta según necesidad)
categorical_columns = data.select_dtypes(include='object').columns
grupo1 = categorical_columns[:12] # Primeras 12 columnas
display(data[grupo1].describe())
| region | Nombre_Departamento | Nombre_Municipio | sitio_def | mes_def | sexo | estado_civil | grupo_edad | nivel_edu | seg_social | asistencia_med | causa_basica | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| count | 78479 | 78479 | 78479 | 78479 | 78479 | 78479 | 78479 | 78479 | 78479 | 78479 | 78479 | 78479 |
| unique | 5 | 33 | 932 | 3 | 12 | 1 | 4 | 16 | 6 | 6 | 3 | 9 |
| top | Andina | BOGOTA DC | BOGOTA DC | Hospital o Clínica | Diciembre | Femenino | Casado | 55-59 años | No especificado | Contributivo | SI | Parte no especificada |
| freq | 48416 | 16939 | 16939 | 43364 | 6782 | 78479 | 24654 | 9373 | 25838 | 33467 | 58251 | 78199 |
Veamos la cantidad de datos faltantes en general.
grafico_datos_faltantes(data)
Análisis Univariado#
Variable: Región#
grafico_circular_categorico(data, 'region', 'Distribución de Defunciones por Región')
grafico_barras_categoricas(data, 'region', 'Distribución de Defunciones por Región', 'Defunciones', 'Número de Defunciones')
Variable: Departamento#
top_10_departamentos = data['Nombre_Departamento'].value_counts().head(10).index
# Filtrar el DataFrame original para que solo contenga esos departamentos
data_top10 = data[data['Nombre_Departamento'].isin(top_10_departamentos)]
# Llamar la función original con el nombre de la columna
grafico_barras_categoricas(data_top10, 'Nombre_Departamento', 'Departamento', 'Cantidad de defunciones', 'Defunciones por departamento (Top 10)')
bottom_10_departamentos = data['Nombre_Departamento'].value_counts().tail(10).index
data_bottom10 = data[data['Nombre_Departamento'].isin(bottom_10_departamentos)]
# Reemplazar el nombre largo por uno más corto en una copia del DataFrame
data_bottom10['Nombre_Departamento'] = data_bottom10['Nombre_Departamento'].replace(
'ARCHIPIÉLAGO DE SAN ANDRÉS Y PROVIDENCIA Y SANTA CATALINA',
'SAN ANDRÉS'
)
grafico_barras_categoricas(data_bottom10, 'Nombre_Departamento', 'Departamento', 'Cantidad de defunciones', 'Defunciones por departamento (Bottom 10)')
Variable: Municipio#
top_10_municipios = data['Nombre_Municipio'].value_counts().head(10).index
data_top10_mun = data[data['Nombre_Municipio'].isin(top_10_municipios)]
grafico_barras_categoricas(data_top10_mun, 'Nombre_Municipio', 'Municipio', 'Cantidad de defunciones', 'Defunciones por municipio (Top 10)')
Variable: Sitio de defunción#
grafico_barras_categoricas(data, 'sitio_def', 'Sitio de defunción', 'Cantidad de registros', 'Distribución sitio de defunción')
grafico_circular_categorico(data, 'sitio_def', 'Distribución de Defunciones por Sitio de Defunción')
Variable: Estado civil#
grafico_barras_categoricas(data, 'estado_civil', 'Estado civil', 'Cantidad de registros', 'Distribución estado civil')
grafico_circular_categorico(data, 'estado_civil', 'Distribución de Defunciones por Estado Civil')
Variable: Grupo de edad#
grafico_edad(data, 'Grupo de edad', 'Cantidad de registros', 'Distribución de Defunciones por Edad')
grafico_barras_categoricas(data, 'grupo_edad', 'Grupo de edad', 'Cantidad de registros', 'Distribución por grupo de edad')
Variable: Nivel educativo#
grafico_barras_categoricas(data, 'nivel_edu', 'Nivel educativo', 'Cantidad de registros', 'Distribución nivel educativo')
grafico_circular_categorico(data, 'nivel_edu', 'Distribución de Defunciones por Nivel Educativo')
Variable: Asistencia médica#
grafico_barras_categoricas(data, 'asistencia_med', 'Asistencia médica', 'Cantidad de registros', 'Distribución asistencia médica')
grafico_circular_categorico(data, 'asistencia_med', 'Distribución de Defunciones por Asistencia Médica')
Variable: Causa básica#
grafico_barras_categoricas(data, 'causa_basica', 'Causa básica', 'Cantidad de registros', 'Distribución causa básica')
Variable: Mes de defunción#
grafico_mes_def(data, 'Mes de defunción', 'Cantidad de registros', 'Distribución de Defunciones por Mes')
grafico_barras_categoricas(data, 'mes_def', 'Mes de defunción', 'Cantidad de registros', 'Distribución de Defunciones por Mes de mayor a menor')
Búsqueda de defunciones por variables#
crear_dashboard_defunciones(data)
Análisis Bivariado#
Tendencia de defunciones por año y región#
data_grouped = data.groupby(['año_def', 'region']).size().reset_index(name='Defunciones')
color_palette = ["#ffb6c1", "#ff69b4", "#db7093", "#c71585",
"#ff1493", "#e60073", "#cc0033", "#b20000"]
fig6 = px.line(data_grouped,
x='año_def',
y='Defunciones',
color='region',
title='Tendencia de Defunciones por Año y Región',
markers=True, # Agregar marcadores
color_discrete_sequence=color_palette) # Aplicar paleta personalizada
fig6.update_layout(
font=dict(family="Bahnschrift", color="black"), # Fuente Bahnschrift en negro
xaxis_title="Año de Defunción",
yaxis_title="Número de Defunciones",
legend_title="Región", # Título de la leyenda
template="plotly_white" # Fondo blanco para mayor claridad
)
fig6.show()
Evolución de las Defunciones según el Lugar de Muerte#
# Agrupar datos por año de defunción y sitio de defunción
data_grouped = data.groupby(["año_def", "sitio_def"]).size().reset_index(name="count")
# Gráfico de líneas con tonalidades rosadas
fig = px.line(data_grouped,
x="año_def",
y="count",
color="sitio_def",
markers=True, # Agregar puntos en la línea
title="Evolución de las Defunciones según el Lugar de Muerte",
color_discrete_sequence=["#ffb6c1", "#ff69b4", "#db7093", "#c71585"]) # Tonos rosados
fig.update_layout(
font=dict(family="Bahnschrift", color="black"),
xaxis_title="Año de Defunción",
yaxis_title="Número de Defunciones",
legend_title="Lugar de Defunción",
template="plotly_white"
)
fig.show()
Evolución de Defunciones por Grupo de Edad#
data_grouped = data.groupby(["año_def", "grupo_edad"]).size().reset_index(name="count")
color_palette = ["#ffb6c1", "#ff69b4", "#db7093", "#c71585",
"#ff1493", "#e60073", "#cc0033", "#b20000",
"#990000", "#800000", "#ff3366", "#ff0033",
"#d40000", "#a10000"]
fig = px.line(data_grouped,
x="año_def",
y="count",
color="grupo_edad",
title="Evolución de Defunciones por Grupo de Edad",
markers=True, # Agregar puntos en la línea
color_discrete_sequence=color_palette, # Aplicar paleta de colores
labels={"grupo_edad": "Grupo de Edad", "año_def": "Año", "count": "Número de Defunciones"})
fig.update_layout(
font=dict(family="Bahnschrift", color="black"), # Fuente en negro
xaxis_title="Año de Defunción",
yaxis_title="Número de Defunciones",
legend_title="Grupo de Edad",
width=800,
height=600,
template="plotly_white"
)
fig.show()
Análisis de los casos a lo largo del tiempo#
meses_map = {
"Enero": "01", "Febrero": "02", "Marzo": "03", "Abril": "04", "Mayo": "05", "Junio": "06",
"Julio": "07", "Agosto": "08", "Septiembre": "09", "Octubre": "10", "Noviembre": "11", "Diciembre": "12"
}
data['mes_def'] = data['mes_def'].map(meses_map)
data['Fecha'] = data['año_def'].astype(str) + '-' + data['mes_def']
conteo_fechas = data['Fecha'].value_counts().reset_index()
conteo_fechas.columns = ['Fecha', 'Cantidad']
conteo_fechas = conteo_fechas.sort_values('Fecha')
conteo_fechas['Fecha'] = pd.to_datetime(conteo_fechas['Fecha'], format='%Y-%m')
fig = px.line(conteo_fechas,
x='Fecha',
y='Cantidad',
title="Casos de Defunción a lo Largo del Tiempo",
labels={'Cantidad': 'Número de Defunciones', 'Fecha': 'Fecha'},
markers=True)
fig.update_traces(line=dict(color="#C2185B"),
marker=dict(color="#F06292", size=8))
fig.update_layout(
template="plotly_white",
xaxis_title="Fecha",
yaxis_title="Número de Defunciones",
font=dict(family="Bahnschrift", size=14, color="black"),
title_font=dict(family="Bahnschrift", size=22, color="black"),
plot_bgcolor="white",
paper_bgcolor="white"
)
fig.show()
Mapa de casos por departamento#
with urlopen('https://raw.githubusercontent.com/lihkir/Uninorte/main/AppliedStatisticMS/DataVisualizationRPython/Lectures/Python/PythonDataSets/Colombia.geo.json') as response:
counties = json.load(response)
locs=[]; z_id=[];
for loc in counties['features']:
loc['id'] = loc['properties']['NOMBRE_DPT']
locs.append(loc['properties']['NOMBRE_DPT'])
z_id.append(loc['properties']['HECTARES'])
colorscale = [
[0, "#fde0dc"], # Rosa claro
[0.2, "#f9bdbb"],
[0.4, "#f69988"],
[0.6, "#f36c60"],
[0.8, "#e84e40"],
[1, "#d50000"] # Rojo intenso
]
# Contar la cantidad de casos por departamento
casos_por_departamento = data['Nombre_Departamento'].value_counts().reset_index()
casos_por_departamento.columns = ['Nombre_Departamento', 'Casos']
# Reemplazar nombres para que coincidan con el GeoJSON
correccion_nombres = {
'ATLÁNTICO': 'ATLANTICO',
'BOLÍVAR': 'BOLIVAR',
'BOGOTA DC': 'SANTAFE DE BOGOTA D.C',
'BOYACÁ': 'BOYACA',
'CÓRDOBA': 'CORDOBA',
'CAQUETÁ': 'CAQUETA',
'CHOCÓ': 'CHOCO',
'LA GUAJIRA': 'LA GUAJIRA',
'ARCHIPIÉLAGO DE SAN ANDRÉS Y PROVIDENCIA Y SANTA CATALINA': 'ARCHIPIELAGO DE SAN ANDRES PROVIDENCIA Y SANTA CATALINA',
'GUAINÍA': 'GUAINIA',
'GUAVIARE': 'GUAVIARE',
'VAUPÉS': 'VAUPES',
'VICHADA': 'VICHADA'
}
casos_por_departamento['Nombre_Departamento'] = casos_por_departamento['Nombre_Departamento'].replace(correccion_nombres)
locs = casos_por_departamento['Nombre_Departamento'].tolist()
z_id = casos_por_departamento['Casos'].tolist()
fig = go.Figure(go.Choroplethmapbox(
geojson=counties,
locations=locs,
z=z_id,
colorscale= colorscale,
colorbar_title="Casos de Defunción"))
fig.update_layout(mapbox_style="open-street-map",
mapbox_zoom=4,
mapbox_center={"lat": 4.570868, "lon": -74.2973328} ,width=800,
height=600 )
fig.show()